package es.unileon.rnag.jgen.operadores;

import java.util.*;
import es.unileon.rnag.jgen.Cromosoma;
import es.unileon.rnag.jgen.genes.*;

/**
 * Clase que implementa la mutaci&oacute;n bit a bit
 * @author Abel Mayorga Gonz&aacute;lez
 * @author Sergio Fern&aacute;ndez Mart&iacute;nez
 * @version 1.0
 */
public class MutacionBasica extends Mutacion {

	/**
	 * Constructor
	 * @param p: Probabilidad de mutaci&oacute;n en tanto por uno.
	 */
	public MutacionBasica(float p){
		super(p);
	}
	
	@Override
	public List<Cromosoma> operar(int generacion, List<Cromosoma> poblacion) {
		List<Cromosoma> nuevos = new ArrayList<Cromosoma>();
		while(!poblacion.isEmpty()){
			//Se obtiene un cromosoma y sus genes
			Cromosoma c = poblacion.remove(0);
			Gen[] genes = c.getGenes();
			//Por cada gen
			for(int i = 0; i < genes.length; i++){
				//Busca una mutacion aceptable
				boolean aceptable = false;
				while(!aceptable){
					//Se obtienen los bits
					char[] bits = genes[i].getBitString().toCharArray();
					boolean mutado = false;
					//Se recorren todos y mutan segun la probabilidad de mutacion
					for(int j = 0; j < bits.length; j++){
						if(Math.random()<_prob){
							if(bits[j]=='1'){
								bits[j] = '0';
							} else {
								bits[j] = '1';
							}
							mutado |= true;
						}
					}
					//Si no se ha mutado, se continua con el siguiente gen
					if(!mutado){
						break;
					} else {
						//Si se ha mutado, se intenta asignar el valor al gen
						//Si se devuelve false es porque el valor no es valido
						String nuevo = new String(bits);
						aceptable = genes[i].asignarValor(nuevo);
					}
				}
			}
			nuevos.add(c);
		}
		return nuevos;
	}

}
